package com.icinfo.cloud.provider.handler;

import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.framework.common.web.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.UnexpectedTypeException;
import javax.validation.ValidationException;
import java.util.List;
import java.util.Set;

/**
 * 描述：全局异常拦截
 *
 * @author xiangyuyu
 * @date 2022-02-22 10:34
 */
@Slf4j
@SuppressWarnings("rawtypes")
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public Result<String> handleNotCatchException(Exception e) {
        log.error("未被捕获的异常 msg:{} 原因:{}", e.getMessage(), e);
        if(!ObjectUtils.isEmpty(e.getMessage())){
            return Result.error(e.getMessage());
        } else {
            return Result.error("系统异常");
        }
    }


    @ExceptionHandler(value = BindException.class)
    public Result<String> handleBind(BindException e) {
        log.error("bing exception", e);
        //抛出的异常可能不止一个
        List<ObjectError> errors = e.getAllErrors();
        StringBuffer sb = new StringBuffer();
        errors.forEach(error -> {
            //打印验证不通过的信息
            sb.append(error.getDefaultMessage() + " ");
        });
        return Result.error("参数绑定异常：" + sb.toString());
    }

    @ExceptionHandler(ValidationException.class)
    public Result<String> handleValidation(ValidationException exception) {
        StringBuffer sb = new StringBuffer();
        if (exception instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) exception;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                //打印验证不通过的信息
                sb.append(item.getMessage() + " ");
            }
        } else if (exception instanceof UnexpectedTypeException) {
            UnexpectedTypeException exs = (UnexpectedTypeException) exception;
            log.error("UnexpectedTypeException:{}", exs.getMessage(), exception);
        }
        log.warn("ValidationException" + sb.toString());
        return Result.error(sb.toString());
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result<String> methodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
        String errorMsg = "";
        for (FieldError error : exception.getBindingResult().getFieldErrors()) {
            errorMsg += error.getField() + ":" + error.getDefaultMessage() + ",";
        }
        errorMsg.substring(0, errorMsg.length() - 1);
        return Result.error(errorMsg);
    }

    @ExceptionHandler(value = BusinessException.class)
    public Result<String> handleBusiness(BusinessException e) {
        log.warn("BusinessException", e);
        return Result.error(e.getMessage());
    }

    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result<String> handleIllegalArgumentException(IllegalArgumentException e) {
        log.warn("BusinessException", e);
        return Result.error(e.getMessage());
    }
}
